from typing import Optional
import pandas as pd
from loguru import logger
from PySide6.QtCore import QTimer
from PySide6.QtWidgets import QSizePolicy

from ui.components.base.base_dialog import TgBaseDialog
from ui.components.layouts.vbox_layout import TgVBoxLayout
from ui.components.composite.tradingview_chart import TgTradingViewChart


class KlineDialog(TgBaseDialog):
    """显示K线图的对话框组件
    
    这是一个可复用的K线图对话框组件，用于显示指定交易品种的K线图表。
    支持通过回调函数获取历史数据，并集成TradingView图表。
    
    Attributes:
        symbol: 交易品种代码
        history_service: 历史数据服务实例
        chart_widget: 图表组件实例
    """
    
    def __init__(self, symbol: str, history_service, show_minutes_buttons: bool = True, parent=None):
        """
        初始化K线图对话框
        
        Args:
            symbol: 交易品种代码
            history_service: 历史数据服务实例，需要实现get_history_data方法
            show_minutes_buttons: 是否显示分钟级周期按钮
            parent: 父窗口
        """
        self.symbol = symbol
        self.history_service = history_service
        self.show_minutes_buttons = show_minutes_buttons
        self.chart_widget = None
        self._is_closing = False
        super().__init__(parent)
        self.setWindowTitle(f"{self.symbol} - K线图")
        self.resize(1000, 700)
        
    def setup_ui(self):
        """设置UI界面"""
        layout = TgVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)  # 移除所有边距
        layout.setSpacing(0)
        
        # 确保对话框有正确的尺寸
        self.setMinimumSize(800, 600)
        
        self.chart_widget = TgTradingViewChart(
            parent=self,
            symbol=self.symbol,
            period_changed_callback=self._fetch_chart_data,
            width=self.width(),  # 使用完整宽度
            height=self.height(),  # 使用完整高度
            show_minutes_buttons=self.show_minutes_buttons
        )
        
        # 设置图表widget的大小策略为扩展
        self.chart_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        
        layout.addWidget(self.chart_widget)
        self.setLayout(layout)

    def showEvent(self, event):
        """
        处理对话框显示事件，确保布局正确
        
        Args:
            event: 显示事件
        """
        super().showEvent(event)
        
        # 确保WebView在对话框显示后有正确的尺寸
        if self.chart_widget and self.chart_widget.web_view:
            # 延迟调整大小，确保布局已经完成
            QTimer.singleShot(100, self._adjust_webview_size)
    
    def _adjust_webview_size(self):
        """调整WebView的大小以匹配对话框"""
        if self.chart_widget and self.chart_widget.web_view:
            # 获取对话框的实际内容区域大小
            content_rect = self.contentsRect()
            new_width = content_rect.width()
            new_height = content_rect.height()
            
            logger.info(f"调整WebView大小: {new_width}x{new_height}")
            
            # 更新WebView大小
            self.chart_widget.web_view.resize(new_width, new_height)
            self.chart_widget.width = new_width
            self.chart_widget.height = new_height
            
            # 强制重新布局
            self.chart_widget.updateGeometry()
            self.updateGeometry()

    def closeEvent(self, event):
        """
        处理对话框关闭事件，清理资源
        
        Args:
            event: 关闭事件
        """
        if self._is_closing:
            event.accept()
            return
            
        self._is_closing = True
        
        try:
            if self.chart_widget:
                logger.info(f"正在清理图表对话框资源: {self.symbol}")
                self.chart_widget.cleanup()
                self.chart_widget = None
        except Exception as e:
            logger.exception(f"清理图表对话框资源时出错: {e}")
        
        super().closeEvent(event)

    def _fetch_chart_data(self, symbol: str, period: str) -> Optional[pd.DataFrame]:
        """
        为图表提供数据的回调函数
        
        Args:
            symbol: 交易品种代码
            period: 时间周期
            
        Returns:
            包含历史数据的DataFrame，如果获取失败则返回空DataFrame
        """
        if self._is_closing:
            return pd.DataFrame()
            
        logger.info(f"为合约 {symbol} 获取周期为 {period} 的数据...")
        try:
            data = self.history_service.get_history_data(symbol, period)
            if data is None or data.empty:
                logger.warning(f"未能获取合约 {symbol} 周期为 {period} 的数据。")
                return pd.DataFrame()
            return data
        except Exception as e:
            logger.exception(f"获取图表数据时出错: {e}")
            return pd.DataFrame()